#include "EpilStatementParser.h"
#include "EpilExpressionStatementParser.h"
#include "EpilFunctionStatementParser.h"
#include "EpilLocalVariableStatementParser.h"
#include "EpilLocalFunctionStatementParser.h"
#include "EpilReturnStatementParser.h"
#include "EpilBreakStatementCode.h"
#include "EpilContinueStatementCode.h"
#include "EpilChunkParser.h"
#include "EpilBlockStatementCode.h"
#include "EpilParserException.h"
#include "EpilIfStatementParser.h"
#include "EpilWhileStatementParser.h"
#include "EpilRepeatStatementParser.h"
#include "EpilForListStatementParser.h"
#include "EpilForNumberStatementParser.h"
#include "EpilPointerHelper.h"


EpilStatementParser::EpilStatementParser( EpilTokenStream & tokens )
: EpilSyntaxParserBase( tokens )
, m_isLastStatement( false )
, m_statement( NULL )
{
}


void EpilStatementParser::Parse()
{
	switch( this->GetTokens().GetCurrentToken().type )
	{
	case ETT_KwIf:
		{
			EpilIfStatementParser ifStatParser( this->GetTokens() );
			ifStatParser.Parse();
			m_statement = ifStatParser.GetStatement();
		}
		break;
	case ETT_KwWhile:
		{
			EpilWhileStatementParser whileStatParser( this->GetTokens() );
			whileStatParser.Parse();
			m_statement = whileStatParser.GetStatement();
		}
		break;
	case ETT_KwDo:
		{
			EpilBlockStatementCode * block = new EpilBlockStatementCode( this->GetTokens().GetCurrentToken().location );
			this->GetTokens().MoveToNext();

			EpilChunkParser chunkParser( this->GetTokens() );
			try
			{
				chunkParser.Parse();
			}
			catch( ... )
			{
				EpilPointerHelper::SafeDelete( block );
				throw;
			}
			block->SetChunk( chunkParser.GetChunk() );
			m_statement = block;

			if( this->GetTokens().GetCurrentToken().type != ETT_KwEnd )
			{
				EpilPointerHelper::SafeDelete( m_statement );
				throw EpilParserException( t("\'end\' expected."), this->GetTokens().GetCurrentToken().location );
			}
			this->GetTokens().MoveToNext();
		}
		break;
	case ETT_KwFor:
		{
			this->GetTokens().MoveToNext();
			switch( this->GetTokens().PeekNextToken().type )
			{
			case ETT_OpAssign:
				{
					EpilForNumberStatementParser fnsParser( this->GetTokens() );
					fnsParser.Parse();
					m_statement = fnsParser.GetStatement();
				}
				break;
			case ETT_OpComma:
			case ETT_KwIn:
				{
					EpilForListStatementParser flsParser( this->GetTokens() );
					flsParser.Parse();
					m_statement = flsParser.GetStatement();
				}
				break;
			default:
				throw EpilParserException( t("\'=\', \',\' or \'in\' expected."), this->GetTokens().PeekNextToken().location );
			}
		}
		break;
	case ETT_KwRepeat:
		{
			EpilRepeatStatementParser repeatStatParser( this->GetTokens() );
			repeatStatParser.Parse();
			m_statement = repeatStatParser.GetStatement();
		}
		break;
	case ETT_KwFunction:
		{
			EpilFunctionStatementParser funcStatParser( this->GetTokens() );
			funcStatParser.Parse();
			m_statement = funcStatParser.GetFunctionStatement();
		}
		break;
	case ETT_KwLocal:
		{
			this->GetTokens().MoveToNext();

			if( this->GetTokens().GetCurrentToken().type == ETT_KwFunction )
			{
				this->GetTokens().MoveToNext();
				EpilLocalFunctionStatementParser lfsParser( this->GetTokens() );
				lfsParser.Parse();
				m_statement = lfsParser.GetStatement();
			}
			else
			{
				EpilLocalVariableStatementParser lvsParser( this->GetTokens() );
				lvsParser.Parse();
				m_statement = lvsParser.GetStatement();
			}
		}
		break;
	case ETT_KwReturn:
		{
			EpilReturnStatementParser returnStatParser( this->GetTokens() );
			returnStatParser.Parse();
			m_statement = returnStatParser.GetStatement();
			m_isLastStatement = true;
		}
		break;
	case ETT_KwContinue:
		{
			m_statement = new EpilContinueStatementCode( this->GetTokens().GetCurrentToken().location );
			this->GetTokens().MoveToNext();
			m_isLastStatement = true;
		}
		break;
	case ETT_KwBreak:
		{
			m_statement = new EpilBreakStatementCode( this->GetTokens().GetCurrentToken().location );
			this->GetTokens().MoveToNext();
			m_isLastStatement = true;
		}
		break;
	default:
		{
			EpilExpressionStatementParser exprStatParser( this->GetTokens() );
			exprStatParser.Parse();
			m_statement = exprStatParser.GetStatement();
		}
	}
}